package com.lmf.queue;

import java.util.Scanner;

/**
 * 利用数组模拟队列的实现：（非环形队列）
 *          程序还存在缺陷，现在队列经历了加满 也全部取出 当前列表理论上为空，
 *          但是任然无法加入数据 这个数组无法复用 只能使用一次 没有到达复用的效果，
 *          需要将这个数组由算法改造成一个环形数组(取模)。
 */
public class ArrayQueueDemo {
    //测试队列
    public static void main(String[] args) {
        //创建一个队列
        ArrayQueue arrayQueue = new ArrayQueue(3);
        Boolean isFlag = true;  //控制循环
        char key = ' '; // 接收用户输入
        Scanner scanner = new Scanner(System.in);
        while (isFlag){
            System.out.println("s(show): 显示队列");
            System.out.println("e(exit): 退出程序");
            System.out.println("a(add): 添加数据到队列");
            System.out.println("g(get): 从队列取出数据");
            System.out.println("h(head): 查看队列头的数据");
            System.out.println("请输入一个字符选项：");
            key = scanner.next().charAt(0); //接收这个字符
            switch (key){
                case 's':
                    arrayQueue.showQueue();
                    break;
                case 'a':
                    System.out.println("请输入一个数：");
                    int value = scanner.nextInt();
                    arrayQueue.addQueue(value);
                    break;
                case 'g':
                    try {
                        System.out.println("队列中的数据："+arrayQueue.getQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'h':
                    try {
                        System.out.println("查看队列头的数据:"+arrayQueue.headQueue());
                    } catch (Exception e) {
                        System.out.println(e.getMessage());
                    }
                    break;
                case 'e':
                    scanner.close();//关闭输入
                    isFlag = false; //控制关闭菜单
                    break;
            }
        }
        System.out.println("程序退出！");
    }
}
class ArrayQueue{
    private int maxSize;    // 表示数组的最大容量
    private int front;  // 队列头部下标
    private int rear;   // 队列尾部下标
    private int[] arr;  // 存放数据  模拟队列

    //创建队列构造器
    public ArrayQueue(int maxSize) {
        this.maxSize = maxSize;
        // 队列头部front和尾部rear 指向队列头部的同一个位置  rear指向队列尾部的具体位置
        this.front = -1;
        this.rear = -1;
        this.arr = new int[maxSize];
    }

    //判断队列是否满
    public Boolean isFull(){
        //尾部rear下标 等于 队列数组存储容量时，表示已满，注意下标是从0开始的，所以容量值要减一
        return rear == maxSize-1;
    }

    //判断是否为空
    public Boolean isEmpty(){
        //尾部下标与头部下标相等的时候，此时两者都等于-1，即队列数组为空，因为数组下标从0开始
        return rear == front;
    }

    //添加数据到队列
    public void addQueue(int data){//传入数据值
        //1.先判断队列是否已满
        if (this.isFull()) {
            System.out.println("队列数组已满，不能再继续添加数据。");
            return;
        }
        //2.若队列没满，则继续添加数据
        rear++; //尾部指针也必须随着后移，以此保证rear永远指向最后一个数据
        arr[rear] = data;
    }

    //获取队列数据
    // （出队列：必须保证数据先入先出，因此就不能随便获取队列数组中的值，只能根据头部指针一个一个获取，否则那就不叫队列了！！！）
    public int getQueue(){
        //1.先判断队列数组是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空，不能从队列获取数据！");
        }
        //2.若队列不为空，再继续弹出数据
        return arr[++front];
    }

    //显示出队列中所有的数据
    public void showQueue(){
        //1.先判断队列数组是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空，没有可以显示的数据！");
        }
        //2.队列不为空，再显示数据
        for (int i : arr) {
            System.out.println(i);
        }
//        for (int i = 0; i < arr.length; i++) {
//            System.out.printf("arr[%d]=%d\n",i,arr[i]);
//        }
    }

    //显示对列的头部的数据  不是取出数据
    public int headQueue(){
        //1.先判断队列数组是否为空
        if (isEmpty()) {
            throw new RuntimeException("队列为空，没有头数据！");
        }
        //2.取出数据
        return arr[front+1];
    }
}